import time, allure, datetime
from Case.python_ui.mylogging.mylogging import MyLogging
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC  # 条件类
from selenium.webdriver.common.keys import Keys
from Case.python_ui.Common.get_path import GetPath
from selenium.webdriver.common.action_chains import ActionChains
from Case.python_ui.PageLocate.organization_locator import OrganizationLocator

from selenium.webdriver.common.by import By
import platform
from selenium.webdriver.support.ui import Select
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains


class Basepage:

    def __init__(self, driver):
        self.driver = driver
        MyLogging().get_logging("driver id:--------------------{}".format(self.driver), "ERROR", "driver test")

    # Wait for elements to be visible
    def wait_elevisble(self, locate, doc, timeout=100, poll_frequency=0.5):
        """
           :param locate:Element positioning mode, primitive form
           :param doc:Currently invoked module name _ Page name _ Operation name
           :param  timeout:Maximum timeout
           :param  poll_frequency
        """
        try:
            MyLogging().get_logging("Wait element{}visible".format(locate), "INFO", doc)
            start_time = datetime.datetime.now()
            WebDriverWait(self.driver, timeout, poll_frequency).until(EC.visibility_of_element_located(locate))
            end_time = datetime.datetime.now()
            wait_times = (end_time - start_time) * 1000
            MyLogging().get_logging(
                "Wait for the element start time{0}，end time{1}，total time{2}".format(start_time, end_time, wait_times),
                doc, "DEBUG")
        except:
            MyLogging().get_logging("Element wait timeout", "INFO", doc)
            # Case execution failed, screenshot
            self.save_screen(doc)
            raise

    # Wait element is not visible
    def wait_eleinvisble(self, locate, doc, timeout=100, poll_frequency=0.5):
        """
           :param locate:Element positioning mode, primitive form
           :param doc:Currently invoked module name _ Page name _ Operation name
           :param  timeout:Maximum timeout
           :param  poll_frequency
        """
        try:
            MyLogging().get_logging("Wait element{}invisible".format(locate), "INFO", doc)
            start_time = datetime.datetime.now()
            WebDriverWait(self.driver, timeout, poll_frequency).until(EC.invisibility_of_element_located(locate))
            end_time = datetime.datetime.now()
            wait_times = (end_time - start_time) * 1000
            MyLogging().get_logging(
                "Wait element invisible start time{0}，end time{1}，total time{2}".format(start_time, end_time,
                                                                                        wait_times), doc,
                "DEBUG")
        except:
            MyLogging().get_logging("Element is not visible wait timeout", "INFO", doc)
            # Case execution failed, screenshot
            self.save_screen(doc)
            raise

    # Find element
    def get_element(self, locate, doc):
        try:
            MyLogging().get_logging("Find element{}".format(locate), "INFO", doc)
            # start_time = datetime.datetime.now()
            ele = self.driver.find_element(*locate)
            # end_time = datetime.datetime.now()
            # wait_times = (end_time - start_time).seconds
            # MyLogging().get_logging("Finds the element start time{0}，end time{1}，total time{2}".format(start_time, end_time, wait_times), doc, "DEBUG")
            return ele
        except:
            MyLogging().get_logging("The element was not found{}".format(locate), "INFO", doc)
            # Use case execution failed, screenshot
            self.save_screen(doc)
            raise

    def get_elements(self, locate, doc):
        try:
            MyLogging().get_logging("Find element{}".format(locate), "INFO", doc)
            eles = self.driver.find_elements(*locate)
            return eles
        except:
            MyLogging().get_logging("The element was not found{}".format(locate), "INFO", doc)
            # Use case execution failed, screenshot
            self.save_screen(doc)
            raise

    def send_keys(self, locate, value, doc):
        try:
            self.get_element(locate, doc).send_keys(value)
        except:
            MyLogging().get_logging("Input{}failed".format(locate), "INFO", doc)
            # Use case execution failed, screenshot
            self.save_screen(doc)
            raise

    # Click element
    def click_element(self, locate, doc):
        # find element
        ele = self.get_element(locate, doc)
        MyLogging().get_logging("Find element{}".format(locate), "INFO", doc)
        try:
            ele.click()
        except:
            MyLogging().get_logging("Element{}Click operation failure".format(locate), "INFO", doc)
            # Use case execution failed, screenshot
            self.save_screen(doc)
            raise

    # screenshots
    def save_screen(self, doc):
        # name is picture name, module name + page name _ Operation name
        file_name = GetPath.screen_shot + "/{0}_{1}.png".format(doc, time.strftime("%Y-%m-%d-%H-%S", time.localtime()))
        try:
            self.driver.save_screenshot(file_name)
            print("current page url:" + self.driver.current_url)
            MyLogging().get_logging("The screenshot is successfully captured. The directory is{}".format(file_name),
                                    "INFO", doc)
            # Test report put screenshots
            with open(file_name, mode='rb') as f:
                file = f.read()
            allure.attach(file, doc, allure.attachment_type.PNG)
        except:
            MyLogging().get_logging("Screenshot failure", "INFO", doc)

    # JS click element
    def click_by_js(self, locate, doc):
        # Find element
        ele = self.get_element(locate, doc)
        MyLogging().get_logging("Find element{}".format(locate), "INFO", doc)
        try:
            self.driver.execute_script('arguments[0].scrollIntoView()', ele)
            self.driver.execute_script('arguments[0].click()', ele)
        except:
            MyLogging().get_logging("Element{}Click operation failure".format(locate), "INFO", doc)
            # screenshots
            self.save_screen(doc)
            raise

    def refresh_user_page(self, user_page_url):
        doc = '刷新页面加载'
        cookies = self.driver.get_cookies()
        print(cookies)
        time.sleep(2)
        self.driver.get(user_page_url)
        self.wait_elevisble(OrganizationLocator.user_management_tab, doc)
        time.sleep(2)
        for cookie in cookies:
            self.driver.add_cookie(cookie)

    def refresh_page(self):
        cookies = self.driver.get_cookies()
        self.driver.refresh()
        self.wait_elevisble(OrganizationLocator.user_management_tab, '刷新页面的加载')
        for cookie in cookies:
            self.driver.add_cookie(cookie)

    # 删除输入框中的内容
    def delete_text(self,locate, doc):
        """
        :param locate:
        :param doc:
        :return:
        """
        try:
            self.click_element(locate,doc)
            self.keyboard_event_all_select(locate,doc)
            self.keyboard_event(locate,doc)
        except:
            MyLogging().get_logging("The element was not found{}".format(locate), "INFO", doc)
            # Case execution failed, screenshot
            self.save_screen(doc)
            raise


    # 键盘删除
    def keyboard_event(self, locate, doc):
        ele = self.get_element(locate, doc)
        ele.send_keys(Keys.CONTROL + "a")
        ele.send_keys(Keys.DELETE)

    # 键盘模拟回车
    def keyboard_event_enter(self, locate, doc):
        ele = self.get_element(locate, doc)
        ele.send_keys(Keys.RETURN)

    # 键盘模拟ctrl+v
    def keyboard_event_copy(self, locate, doc):
        ele = self.get_element(locate, doc)
        ele.click()
        os = platform.system()
        if os == 'Darwin':
            ActionChains(self.driver).key_down(Keys.COMMAND).send_keys("v").key_up(Keys.COMMAND).perform()
        else:
            ActionChains(self.driver).key_down(Keys.CONTROL).send_keys("v").key_up(Keys.CONTROL).perform()

    # 键盘模拟ctrl+A
    def keyboard_event_all_select(self, locate, doc):
        ele = self.get_element(locate, doc)
        ele.click()
        os = platform.system()
        if os == 'Darwin':
            ActionChains(self.driver).key_down(Keys.COMMAND).send_keys("a").key_up(Keys.COMMAND).perform()
        else:
            ActionChains(self.driver).key_down(Keys.CONTROL).send_keys("a").key_up(Keys.CONTROL).perform()

    # body向右移动
    def keyboard_move(self, locate,length, doc):
        ele = self.get_element(locate, doc)
        # 使用 JavaScript 将 tbody 元素向右移动 100px，你可以根据实际需要调整移动的距离
        self.driver.execute_script("arguments[0].style.transform = 'translateX(-"+length+"px)';", ele)


    # 执行js操作
    def excute_js(self, js):
        self.driver.execute_script(js)

    # Move to the element and click
    def move_mouse_to_click_element(self, locate, doc):
        try:
            MyLogging().get_logging("Find element{}".format(locate), "INFO", doc)
            ele = self.driver.find_element(*locate)
            ActionChains(self.driver).move_to_element(ele).click().perform()
        except:
            MyLogging().get_logging("The element was not found{}".format(locate), "INFO", doc)
            # Case execution failed, screenshot
            self.save_screen(doc)
            raise

    def move_mouse_to_element(self, locate):
        ele = self.driver.find_element(*locate)
        ActionChains(self.driver).move_to_element(ele).perform()

    def switch_to_new_window(self):
        current_window = self.driver.current_window_handle
        all_windows = self.driver.window_handles
        new_window = [window for window in all_windows if window != current_window][0]
        self.driver.switch_to.window(new_window)

    # 鼠标悬浮展示数据项并点击
    def move_mouse_to_element_clicklink(self, locate, link_text, doc):
        """
        :param locate:
        :param link_text: 鼠标悬浮后展示的数据项名字
        :param doc:
        :return:
        """
        try:
            MyLogging().get_logging("Find element{}".format(locate), "INFO", doc)
            ele = self.driver.find_element(*locate)
            ActionChains(self.driver).move_to_element(ele).click().perform()
            self.driver.find_element(By.LINK_TEXT, link_text).click()
        except:
            MyLogging().get_logging("The element was not found{}".format(locate), "INFO", doc)
            # Case execution failed, screenshot
            self.save_screen(doc)
            raise

    # 切换新窗口
    def change_windows(self, doc, index=-1, timeout=30, poll_frequency=0.2):
        """

        :param index: -1 最后一次打开的窗口  0 最开始的窗口
        :param doc:
        :return: 当前窗口url，id
        """
        try:
            new_windows = self.driver.window_handles[index]
            time.sleep(5)
            # WebDriverWait(self.driver, timeout, poll_frequency).until(EC.new_window_is_opened(new_windows))
            self.driver.switch_to.window(new_windows)
            return self.driver.current_window_handle, self.driver.window_handles
        except:
            MyLogging().get_logging("The element was not found{}".format(self.driver.current_window_handle), "INFO",
                                    doc)
            # Case execution failed, screenshot
            self.save_screen(doc)
            raise

    # 拖动滑动窗口到最右边  方法待拓展
    def action_right(self, locate, doc, xoffset=0, yoffset=0):
        """

        :param locate:
        :param doc:
        :param xoffset:
        :param yoffset:
        :return:
        """
        # element = self.driver.find_element(*locate)
        # ActionChains(self.driver).drag_and_drop_by_offset(element, 0, 0)
        element = self.driver.find_element(*locate)
        self.driver.execute_script("arguments[0].scrollLeft = arguments[0].scrollWidth", element)

    def scroll_bar_operation(self, locate):
        '''
        滚动到元素可见
        '''
        element = self.driver.find_element(*locate)
        self.driver.execute_script("arguments[0].scrollIntoView();", element)

    def scroll_bar_operation2(self,locate,scroll_lines=10,down=1):
        """
        元素不可定位的时候，需要滚动到元素才能定位
        :param locate:
        :param scroll_lines: 滚动的行数
        :param down: 1 是往下滚动，其余往上滚动
        :return:
        """
        element = None
        max_attempts = 10  # 设置最大尝试次数
        #scroll_lines = 10  # 向下滚动3行
        # 模拟向下滚动查找元素，限制尝试次数防止死循环
        attempts = 0
        if down==1:
            while element is None and attempts < max_attempts:
                try:
                    element = self.driver.find_element(*locate)
                    break
                except:
                    actions = ActionChains(self.driver)
                    for _ in range(scroll_lines):
                        actions.send_keys(Keys.ARROW_DOWN).perform()
                    attempts += 1
        else:
            while element is None and attempts < max_attempts:
                try:
                    element = self.driver.find_element(*locate)
                    break
                except:
                    actions = ActionChains(self.driver)
                    for _ in range(scroll_lines):
                        actions.send_keys(Keys.ARROW_UP).perform()
                    attempts += 1



    # 判断是否是隐藏元素
    def is_element_disabled(self, locate):
        element = self.driver.find_element(*locate)
        return element.is_enabled()

    # 获取元素的属性值
    def get_attribute(self,locate,attribute,doc):
        """

        :param locate:
        :param attribute:
        :return:
        """
        try:
            MyLogging().get_logging("get_attribute{}".format(locate), "INFO", doc)
            # start_time = datetime.datetime.now()
            ele = self.driver.find_element(*locate)
            placeholder_value = ele.get_attribute(attribute)
            # end_time = datetime.datetime.now()
            # wait_times = (end_time - start_time).seconds
            # MyLogging().get_logging("Finds the element start time{0}，end time{1}，total time{2}".format(start_time, end_time, wait_times), doc, "DEBUG")
            return placeholder_value
        except:
            MyLogging().get_logging("The element was not found{}".format(locate), "INFO", doc)
            # Use case execution failed, screenshot
            self.save_screen(doc)
            raise

    def get_table_list(self, locate):
        # 返回该元素定位的所有元素集合
        ele = self.driver.find_elements(*locate)
        list = []
        # 对返回的页面元素遍历
        for i in ele:
            # 返回页面元素的文本内容
            text = i.get_attribute("textContent")
            MyLogging().get_logging("该元素的内容是{0}".format(i.get_attribute("textContent")))
            # 将文本内容添加到列表中保存
            list.append(text)
        # 返回列表信息
        return list

    # 清空input元素 value的值
    def element_clear(self, locate, doc):
        """

        :param locate:
        :param doc:
        :return:
        """
        try:
            MyLogging().get_logging("get_attribute{}".format(locate), "INFO", doc)
            ele = self.driver.find_element(*locate)
            self.driver.execute_script("arguments[0].value = '';", ele)
        except:
            MyLogging().get_logging("The element was not found{}".format(locate), "INFO", doc)
            # Use case execution failed, screenshot
            self.save_screen(doc)
            raise

    # 双击
    def double_click(self, locate, doc):
        """

        :param locate:
        :param doc:
        :return:
        """
        try:
            MyLogging().get_logging("get_attribute{}".format(locate), "INFO", doc)
            ele = self.driver.find_element(*locate)
            actions = ActionChains(self.driver)
            actions.double_click(ele).perform()
        except:
            MyLogging().get_logging("The element was not found{}".format(locate), "INFO", doc)
            # Use case execution failed, screenshot
            self.save_screen(doc)
            raise

    # 校验某个属性值是否符合预期
    def check_attribute(self, real_result, except_result):
        if real_result == except_result:
            assert True
        else:
            assert False, '实际值:' + real_result + '期望值:' + except_result

if __name__ == '__main__':
    driver = webdriver.Chrome()
    Basepage(driver)